約 281,903 件
https://w.atwiki.jp/prepress-tips/pages/142.html
最終更新日時: 2008/06/30 pdfを調べるツール 使い方の例 Edit pdfを調べるツール 私が現在利用しているものです。 PDF Analyst pdfのオブジェクトに関する情報を すばやく見ることができます。 PDF FontDecoder pdfのフォントに関する情報を すばやく見ることができます。 TSXBIN シンボル表示のできる驚異的なバイナリエディタです。 pdfに限らず ほとんどすべてのデータを シンボリックに見ることができます。 pdfを見るときは 下のマクロを使います。 ※スピードが遅かったり ときどきハングアップしたりもしますが それなりに使えます。 利用は無保証ですが ご自由にどうぞ。 pdf.sym // 初期設定 // 詳細 // --- maxloop #maxloop -1 // --- typedef.h typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int UINT; typedef unsigned long DWORD; typedef unsigned long ULONG; typedef long LONG; typedef int BOOL; const BOOL TRUE=1; const BOOL FALSE=0; // --- 定数・変数の宣言 unsigned long FileSize, pos, pos_xref, pos_obj; unsigned long o_num, o_cnt, o_off, o_bck, l, o_i, o_j, o_k; unsigned long x_i; unsigned char c, eol_c; unsigned char st; string str, TmpStr; unsigned short OBJ_max = 1000; unsigned long OBJ_top[ OBJ_max ]; unsigned short OBJ_cnt; unsigned long OBJ_srt[ OBJ_max ]; unsigned long OBJ_num[ OBJ_max ]; // --- objectオフセットを初期化 for( o_i = 0; o_i OBJ_max; o_i++ ) { OBJ_top[ o_i ] = 0; OBJ_num[ o_i ] = o_i; } // --- シンボル表示するかどうかを確認 if( MessageBox( シンボル表示します(多少時間がかかります。) , TSXBIN , 1 ) == 2 ) { return; } // pdfの構造を調べる // 詳細 // 最新の相互参照表のオフセットを調べる // 詳細 // --- ファイルサイズを読む FileSize = GetFileSize(); // --- ファイルの終わりから s を探す pos = FileSize; c = \0 ; while( c != s ) { c = GetByte( --pos ); } // --- startxref を探す // ( 見つからないときは中止 ) while( FStrCmp( pos, 0, startxref ) != 0 ) { pos++; if( pos == FileSize ) { pos = 0; MessageBox( startxrefが見つかりません。 , TSXBIN , 0 ); return; } } // --- 数字以外を読み飛ばして c = GetByte( pos++ ); while( c 0 || 9 c ) { c = GetByte( pos++ ); } // --- xrefオフセットを読み pos_xref = 0; while( 0 = c && c = 9 ) { pos_xref = 10 * pos_xref + c - 0 ; c = GetByte( pos++ ); } // --- object配列に格納する x_i = OBJ_max - 1; OBJ_top[ x_i ] = pos_xref; OBJ_num[ x_i ] = OBJ_max; // 注 // object番号をOBJ_maxにしておく // (あとで相互参照表であることを判別するため) // --- xrefオフセットが oでなければ繰り返す { while( pos_xref != 0 ) { // 詳細 // 相互参照表のオブジェクトの一覧を読む // --- 行末文字の判別 // xrefオフセットの位置に移動して // 行末文字まで読み飛ばし pos = pos_xref; c = GetByte( pos++ ); while( ! ( c == 0x0d || c == 0x0a ) ) { c = GetByte( pos++ ); } // 行末文字を読み取る eol_c = c; c = GetByte( pos ); if( c == 0x0a ) { pos++; eol_c = c; } // --- objectオフセットの取得 // while // trailer で始まる箇所まで 繰り返す while( FStrCmp( pos, 0, trailer ) != 0 ) { // { // --- object番号の始まりとobjectの個数を読む // --- 詳細 // 1文字目を読む c = GetByte( pos++ ); // 空白と行末文字を読み飛ばし while( c == 0x20 || c == 0x0d || c == 0x0a ) { c = GetByte( pos++ ); } // object番号の始まりを読む o_num = 0; while( 0 = c && c = 9 ) { o_num = 10 * o_num + c - 0 ; c = GetByte( pos++ ); } // 空白と行末文字を読み飛ばし while( c == 0x20 || c == 0x0d || c == 0x0a ) { c = GetByte( pos++ ); } // objectの個数を読む o_cnt = 0; while( 0 = c && c = 9 ) { o_cnt = 10 * o_cnt + c - 0 ; c = GetByte( pos++ ); } // 空白と行末文字を読み飛ばし while( c == 0x20 || c == 0x0d || c == 0x0a ) { c = GetByte( pos++ ); } // 1文字戻す pos--; if( 0 o_cnt ) { // for // objectの個数分繰り返す for( o_i = 0; o_i o_cnt; o_i++ ) { // { // --- objectオフセットを読み OBJ_topに格納する // --- 詳細 // 文字位置を記憶 pos_obj = pos; // if // 使用中のエントリなら if( GetByte( pos + 17 ) == n ) { // { // 1文字目を読む c = GetByte( pos++ ); // 空白を読み飛ばして while( c == 0x20 ) { c = GetByte( pos++ ); } // objectオフセットを読み o_off = 0; while( 0 = c && c = 9 ) { o_off = 10 * o_off + c - 0 ; c = GetByte( pos++ ); } // objectオフセットの配列に格納する OBJ_top[ o_num + o_i ] = o_off; } // 文字位置を復元し 20進める pos = pos_obj + 20; } } } // --- startxrefの検索と // --- xrefオフセットの取得 // xrefオフセットをクリア pos_xref = 0; // while // startxref で始まる箇所まで 繰り返す while( FStrCmp( pos, 0, startxref ) != 0 ) { // { // --- prevエントリを読む // --- 詳細 // if // prevエントリなら if( FStrCmp( pos, 0, /prev , 1 ) == 0 ) { // { // 数字以外を読み飛ばして c = GetByte( pos++ ); while( c 0 || 9 c ) { c = GetByte( pos++ ); } // xrefオフセットを読み pos_xref = 0; while( 0 = c && c = 9 ) { pos_xref = 10 * pos_xref + c - 0 ; c = GetByte( pos++ ); } if( OBJ_top[ x_i ] != pos_xref ) { // object配列に格納する OBJ_top[-- x_i ] = pos_xref; OBJ_num[ x_i ] = OBJ_max; } else { pos_xref = 0; } // 1文字戻す pos--; } // 次の文字位置へ pos++; // ファイルの終わりだったら中止 if( pos == FileSize ) { MessageBox( startxrefが見つかりません。 , TSXBIN , 0 ); pos = 0; return; } } // --- } } // --- ソート // --- objectオフセットのソート // for // OBJ_topの最後まで繰り返し OBJ_cnt = 0; for( o_i = 0; o_i OBJ_max; o_i++ ) { // { // if // objectオフセットが 0でないとき if( OBJ_top[ o_i ] != 0 ) { // { // objectオフセットとobject番号を読む o_off = OBJ_top[ o_i ]; o_num = OBJ_num[ o_i ]; // if // 1つ目でなく if( 0 OBJ_cnt ) { // { // if // OBJ_srtの最終オフセットより小さいとき if( ( 0 OBJ_cnt ) && ( o_off OBJ_srt[ OBJ_cnt - 1 ] ) ) { // { // 格納場所をサーチ for( o_k = 0; o_k OBJ_cnt; o_k++ ) { if( o_off OBJ_srt[ o_k ] ) { o_j = o_k; break; } } // 格納場所を空ける for( o_k = o_j; o_k OBJ_cnt; o_k++ ) { o_bck = OBJ_srt[ o_k ]; OBJ_srt[ o_k ] = o_off; o_off = o_bck; o_bck = OBJ_num[ o_k ]; OBJ_num[ o_k ] = o_num; o_num = o_bck; } // } } // } } // objectオフセットとobject番号をOBJ_srtに格納 OBJ_srt[ OBJ_cnt ] = o_off; OBJ_num[ OBJ_cnt ] = o_num; OBJ_cnt++; // } } // } } // ファイル末オフセットも格納 OBJ_srt[ OBJ_cnt ] = FileSize; OBJ_num[ OBJ_cnt++ ] = OBJ_max; // オブジェクト数の確認 if( MessageBox( オブジェクト数は + tostr( OBJ_cnt - ( OBJ_max - x_i ) ) + です。 , TSXBIN , 1 ) == 2 ) { return; } // --- オブジェクトを表示 // hedderの表示 TmpStr = header ; pos = 0; while( pos OBJ_srt[ 0 ] ) { pos_obj = pos; while( pos OBJ_srt[ 0 ] ) { c = GetByte( pos++ ); if( c == 0x0d ) { c = GetByte( pos++ ); if( c != 0x0a ) { pos--; } break; } if( c == 0x0a ) { break; } } l = pos - pos_obj; $BYTE TmpStr[ l ]; } // --- objectsの表示 // for // objectの個数分繰り返し for( o_j = 1; o_j OBJ_cnt; o_j++ ) { // { // 位置の確認( デバグ用 ) if( ( o_j - 1 ) == OBJ_cnt ) { if( MessageBox( OBJ_srt[ + tostr( o_j - 1 ) + ] + tostr( OBJ_srt[ o_j - 1 ] ) + pos + tostr( pos ), TSXBIN , 1 ) == 2 ) { return; } } // if // objectのとき if( OBJ_num[ o_j - 1 ] OBJ_max ) { // { // --- obectを表示する // obj の表示 TmpStr = obj + tostr( OBJ_num[ o_j - 1 ] ); // objectの表示 st = 0; while( pos OBJ_srt[ o_j ] ) { pos_obj = pos; if( st == 2 ) { while( pos OBJ_srt[ o_j ] ) { l = FindByteOffset( e , pos ); l++; pos += l; if( OBJ_srt[ o_j ] pos ) { pos = OBJ_srt[ o_j ]; } if( FStrCmp( pos - 1, 0, endstream ) == 0 ) { pos--; break; } } st = 0; } else { if( st == 1 ) { st = 2; } while( pos OBJ_srt[ o_j ] ) { c = GetByte( pos++ ); if( c == ) { if( FStrCmp( pos, 0, stream ) == 0 ) { break; } } if( c == 0x0d ) { c = GetByte( pos++ ); if( c != 0x0a ) { pos--; } break; } if( c == 0x0a ) { break; } } if( FStrCmp( pos, 0, stream ) == 0 ) { st = 1; } } l = pos - pos_obj; $BYTE TmpStr[ l ]; } // } else { } else { // --- xrefを表示する // --- 詳細 // xref の表示 TmpStr = xref ; l = FindByte( eol_c ); l++; pos += l; $BYTE TmpStr[ l ]; // for // trailer まで繰り返す while( FStrCmp( pos, 0, trailer ) != 0 ) { // { // --- object番号の始まりとobjectの個数を読んで表示する // --- 詳細 // 文字位置を記憶 pos_obj = pos; // 1文字目を読む c = GetByte( pos++ ); // 空白を読み飛ばし while( c == 0x20 ) { c = GetByte( pos++ ); } // object番号の始まりを読む o_num = 0; while( 0 = c && c = 9 ) { o_num = 10 * o_num + c - 0 ; c = GetByte( pos++ ); } // 空白を読み飛ばし while( c == 0x20 ) { c = GetByte( pos++ ); } // objectの個数を読む o_cnt = 0; while( 0 = c && c = 9 ) { o_cnt = 10 * o_cnt + c - 0 ; c = GetByte( pos++ ); } // 空白と行末文字を読み飛ばし while( c == 0x20 || c == 0x0d || c == 0x0a ) { c = GetByte( pos++ ); } // 1文字戻す pos--; // 文字数を計算 l = pos - pos_obj; // object番号の始まりとobjectの個数を表示 $BYTE TmpStr[ l ]; // for // objectの個数分繰り返す for( o_i = 0; o_i o_cnt; o_i++ ) { // { // 20バイト表示 TmpStr = xref + tostr( o_num + o_i ); l = 20; pos += l; $BYTE TmpStr[ l ]; } // } } // --- trailerを表示する // trailer の表示 TmpStr = trailer ; // trailerの表示 while( pos OBJ_srt[ o_j ] ) { pos_obj = pos; while( pos OBJ_srt[ o_j ] ) { c = GetByte( pos++ ); if( c == 0x0d ) { if( pos OBJ_srt[ o_j ] ) { c = GetByte( pos++ ); if( c != 0x0a ) { pos--; } } break; } if( c == 0x0a ) { break; } } l = pos - pos_obj; $BYTE TmpStr[ l ]; } // } } // } } 使い方の例 たとえば pdfから cmapを取り出すときは 次のようにします。 PDF FontDecoderで フォントのオブジェクト番号を調べる。 PDF Analystで そのオブジェクトを調べて エンコーディングを知る。/Encoding/Identity-H のときは /BaseFontエントリで サブフォントの名前がわかり /ToUnicodeエントリで Cmapのオブジェクト番号がわかる。 TSXBINで そのオブジェクトを取り出す。 inflate.plで それをインフレートする。 ※ inflate.plは perlのDocumentationのCompress Zlibのところに記載されています。 inflate.pl use strict ; use warnings ; use Compress Zlib ; my $x = inflateInit() or die Cannot create a inflation stream\x0a ; my $input = ; binmode STDIN; binmode STDOUT; my ($output, $status) ; while (read(STDIN, $input, 4096)) { ($output, $status) = $x- inflate(\$input) ; print $output if $status == Z_OK or $status == Z_STREAM_END ; last if $status != Z_OK ; } die inflation failed\x0a unless $status == Z_STREAM_END ; Edit
https://w.atwiki.jp/wiki1_test/pages/2805.html
https://w.atwiki.jp/sevenlives/pages/515.html
Adobe? PostScript Evince Popper? GhostScript? ANSI?CGATS?
https://w.atwiki.jp/ssfs/pages/136.html
http //www46.atwiki.jp/ssfs?cmd=upload act=open pageid=8 file=ATM%E3%82%AB%E3%83%BC%E3%83%89%E5%86%8D%E7%99%BA%E8%A1%8C.pdf
https://w.atwiki.jp/kelaf/pages/43.html
Foxit PDF Reader adobeより軽快なPDFビューア ■参考
https://w.atwiki.jp/izu6105/pages/349.html
ペンタブを使って PDFファイルに手書きが 出来るソフト、便利そうですね。 PDFファイルの使い方の幅が 広がりそうですね。 ヤフーニュース PDFファイル 関連商品はこちらPDFファイル
https://w.atwiki.jp/rffbl22/pages/61.html
pdfからの画像の抽出 pdfには画像とテキストが保存されているが、画像部分だけ抽出して保存する方法を説明する。 ただし、pdfファイルのセキュリティ設定によっては抽出できない。 方法 1. ファイル⇒開く でpdfファイルを選択する 2. PDFの読み込み のダイアログが現れる 3. 選択⇒画像 とすると画像だけが表示される 4. 保存したい画像を選んで OK を選ぶ 5. photoshop上でウィンドウに表示される 6. ファイル⇒保存 で任意のファイル形式を指定する。pngとか(インターレースは、なしでOK) 残念ながらepsとかを選んでもベクトル画像として、illustratorで線や文字を編集したりはできない。
https://w.atwiki.jp/jboy/pages/21.html
VectorWorks→PDF
https://w.atwiki.jp/epolitics/pages/158.html
国会での審議の中継 衆議院・法務委員会(2004/06/02)/松野信夫議員(民主党所属)どういうケースで二重国籍が発生しているか? 重国籍者の統計数字 政府は重国籍者をどのように把握しているのか? 何故、政府は重国籍を容認しないのか? 旧国籍法の時代に重国籍になった場合について 国籍選択制度について 今までの質疑の中間取りまとめ 親の介護のために帰国する元日本人の便宜はどうなっているのか? 元日本国籍保持者の帰化について 国会での審議の中継 衆議院インターネット審議中継 http //www.shugiintv.go.jp/jp/index.cfm 衆議院-会議録 http //www.shugiin.go.jp/index.nsf/html/index_kaigiroku.htm 衆議院・法務委員会(2004/06/02)/松野信夫議員(民主党所属) 松野信夫 - Wikipedia ○松野(信)委員 民主党の松野信夫です。 (中略) どういうケースで二重国籍が発生しているか? それでは、当初予定をしておりました二重国籍の問題について御質問をさせていただきたいと思います。 二重国籍の問題については、これまでにも別の機会に取り上げて質問されておられる委員もおりました。だんだんこの二重国籍の問題が広く関心を持たれ始めている、このように認識をしております。 私は、基本的には二重国籍を容認していいではないか。確かに現行法は国籍唯一の原則というのをとっておるわけですけれども、その場合のメリット、デメリット、そして二重国籍を容認した場合のメリット、デメリット、双方比較をして、二重国籍を容認した場合のメリットの方が私ははるかに大きい、このように考えておりますので、結論的にはその方向で御質問をさせていただきたいと思っております。 それで、まず、どういう場面で二重国籍が発生をするのか。幾つか想定されている場面、こういう場面で発生をするというのは幾つか報告などはされておりますが、もしよろしければ、頻度、考えられる多さの順ですか、そういうことにも触れながら、こういう場合に主に発生をしているというのを御指摘いただければと思います。 ○房村政府参考人 重国籍が発生する場合でございますが、大きく分けますと、出生によって重国籍を取得する場合と、それから、出生後、何らかの身分行為を行うことによって取得する場合がございます。 まず最初の、出生による場合を御説明いたしますと、我が国の国籍法では、父母のいずれかが日本国籍を有していますと、その子供は日本国籍を取得する、こうなっておりますので、父親または母親のいずれかが日本国民でありますと、その子供も日本国籍を取得します。したがいまして、その相手方、例えば父親が日本人である場合に、母親が外国人で、しかも同様の血統主義をとっているという場合には、その子供は母親の方の国籍も取得する。例えば韓国は父母両血統主義をとっておりますので、日本人の親と韓国人の親が結婚をして子供が生まれますと、子供は日本国籍と韓国の国籍の双方を取得する。こういうことで重国籍を取得する場合がございます。 一般に国籍取得の原因としては血統主義は相当幅広くとられておりますので、やはり生ずる場合としては、出生によって、しかも両血統主義の関係で取得する場合は相当多いのではないかと思われます。 次に、もう一つ、国籍を取得する原因として、生地主義、生まれた国、その国で生まれますと、両親の国籍を問わずに国籍を与えるという国がございます。代表的な例がアメリカでございます。したがいまして、日本人の親の子供で、アメリカで生まれますとアメリカ国籍を取得する、同時に、当然親の関係で日本国籍も取得する、重国籍が生ずるという場合がございます。 そのほか、出生後の身分行為による場合といたしましては、例えば外国人の父からの認知を受ける。その外国人の本国法が認知によって子供に国籍を与える、こういう仕組みになっておりますと、認知によってその外国国籍も取得いたしますので、母親からの日本国籍とあわせて重国籍になるという場合がございます。 それから、養子縁組でも同様の法制をとっている国もありますので、養子縁組をすることによって重国籍になる場合、それと婚姻によってなる場合、そういったものがございますが、数としてはそう多くはないだろうと思っております。 重国籍者の統計数字 ○松野(信)委員 この重国籍は、恐らく統計的に見てもだんだんだんだんとふえていっているのではないかなというふうに思います。 その一つの指標としては、国際結婚の数、私の方でも調べてみましたけれども、例えば一九八五年、昭和六十年、このとき新しい国籍法が施行されていますが、このときに一万二千百八十一名、件数としてはあった。それが二〇〇二年、平成十四年には三万五千八百七十九ということでかなりふえて、要するに、国際結婚がふえているということが一つの裏づけとしてはあって、恐らく重国籍者の数も次第にふえていっているのではないか、このように思っておりますが、この重国籍者の数を正確に把握するのはなかなか難しいところもあろうかと思いますが、現実にふえているのか減っているのか、大体どの程度存在すると考えておられるのか、この点はいかがですか。 ○房村政府参考人 重国籍者数でございますが、昭和五十九年の改正国籍法の施行前についてはちょっと把握はしておりません。その後につきましては、判明する限りでの数ということで、それが完全な重国籍者数を把握しているとは言いがたいわけでありますが、少なくとも当方が把握している範囲では次第にふえてきております。 昭和六十年当時は年間約一万人程度でございましたが、次第にふえまして、平成四年ごろには二万人程度になりまして、平成十四年では約三万三千人を超えているというのが私どもの把握している数でございます。 政府は重国籍者をどのように把握しているのか? ○松野(信)委員 この重国籍者については、要するに国籍選択ということで、二十を過ぎてからとか、国籍唯一の原則に基づいてどちらか選びなさい、こうなっているんですが、この重国籍者については、政府の方で積極的に捜索をして重国籍者を見つけて選択の通知などをしているのか、それとも、たまたま何らかの理由で発見されるというような状態になっているのか、その辺はどうですか。 ○房村政府参考人 重国籍者をどのように把握しているかという問題でございますが、これは、身分行為、例えば婚姻あるいは出生ということがありますと、市町村に届け出がなされます。それは監督法務局の方に届け書が送付されますので、監督法務局の方で、送付を受けた届け書等から重国籍者が判明する限りにおいて把握をしている、それ以上に積極的に捜索をするというようなことはしておりません。 何故、政府は重国籍を容認しないのか? ○松野(信)委員 それでは次に、重国籍を容認していないのが現行法ですけれども、なぜ重国籍を容認しないのか、重国籍を容認するとどういうような問題あるいは弊害というのが発生する、このように考えておられるのか、この点についてお答えください。 ○房村政府参考人 御指摘のように、現在の国籍法は、できるだけ国籍は一つにしたいということで、いわゆる国籍唯一の原則というものを採用しているわけでございます。 重国籍の場合の弊害ということですが、やはり二つの国籍を持ちますと、どうしても二つの国に対する忠誠が衝突をする、あるいは、国の方からいいますと外交保護権が衝突をする、そういうことによって問題が生ずるおそれがあるということがまずあるわけでございます。 それから、重国籍ということになりますと、それぞれの国で身分関係を管理するといいますか、登録をするということになります。そういたしますと、例えばAとBの両方の国籍を持っていて、Aの国で婚姻をしたことについてはA国が把握をする、それをまた独立にB国の方で身分関係を把握いたしますので、重婚というような関係が生じやすくなる。そういうことから、身分関係に混乱が生ずるおそれがあるということが言われているわけでございます。 そのほかいろいろあろうかと思いますが、大きく申し上げますと、以上のような点が重国籍の弊害と言われております。 ○松野(信)委員 この点については少しこれから議論をしたいと思いますが、今御指摘があった、両方の国籍を持つと、忠誠義務、どっちの国に忠誠を尽くすんだということで、これは恐らく、具体的にあらわれてくるのが兵役の問題だろうというふうに思います。それからもう一つ、外交保護権について、これが両方からの抵触があるんじゃないか。そしてまた、身分上、特に重婚あたりが発生する。大きく今三点ぐらい御指摘があったかなというふうに思います。 通常、そういうことがよく言われているんですが、ただ、現実問題として、そういうような弊害が現に日本で発生をしたということがあるのか。先ほど、重国籍者の数、想定すると現在も三万人以上おられるということですけれども、現実にこういうような、今三つ挙げられたような弊害が現に発生をして、トラブったというようなことがあるのかどうか、この点はどうですか。 ○房村政府参考人 古いことはわからないんですが、最近におきまして、私どもとして、具体的に重国籍で何らかの問題が生じたという事例は把握しておりません。 それから、先ほど申し上げた数字、例えば三万人近い重国籍者というのは、平成十四年において新たに発生した重国籍者数でございます。 ○松野(信)委員 では、ちょっとそれで確認しておきますが、そうすると、平成十四年で大体三万人ぐらい発生したというと、累積としてはもっとそれよりずっと多いということになるんでしょうか。そうすると、累積としては、重国籍者は大体どれくらいおられるというふうに把握していますか。 ○房村政府参考人 これは先ほど申し上げました数字、大体、各年において先ほど申し上げたような届け出書等から把握した概数を申し上げたわけでございます。その各年で把握した重国籍者として発生されたと思われる数を昭和六十年から平成十四年までを単純に合計いたしますと、約四十万人ということになります。 ただ、その後の国籍の変化は必ずしも追跡調査をしているわけではございませんので、現段階においてそのとおりの数がいるかどうかは必ずしもはっきりいたしません。 ○松野(信)委員 重国籍を容認したときの弊害を言われましたけれども、現実に、これまでその弊害が現実化したということもないようであります。重国籍を容認するというのは、G8を含め、世界各国、かなりたくさんあるわけですけれども、そこでも重国籍を容認したことによるトラブルというのは現実にはほとんど発生をしていないのではないか、このように理解をしております。 忠誠義務が衝突するということで、具体的には兵役の問題が出てくるかと思いますが、そもそも日本の場合ですと、憲法九条の関係で戦争放棄をうたっているわけで、徴兵制もありませんので、この兵役の問題というのはまず日本では問題にならないのではないか、このように考えております。 諸外国についても調べてみましたけれども、いわゆる先進国では、徴兵制というのは非常に少なくなってきているわけです。 少し申し上げますと、アメリカは志願兵制、カナダも志願兵制、イギリスも志願兵制。イタリアは、現在は徴兵制ですけれども、これは二〇〇六年までに志願兵制に移行するという予定。フランスは志願兵制でありまして、これは二〇〇三年に徴兵制を廃止している。こういうようなのが諸外国でございます。 ちなみに、アジアは必ずしもそうなっていないところがありまして、韓国は御承知のように徴兵制、中国については選抜的な徴兵制がなされている、こういうような実態であります。 ただ、韓国も徴兵制は採用していますけれども、新聞報道などによりますと、韓国人の夫婦がアメリカに行って子供を出産するという例がたくさんあって、このツアーができているそうで、アメリカは生地主義ですから、そうするとアメリカの市民権が取れるということで、変な言い方ですけれども、徴兵制逃れというような現象も起きているようでございます。 そうすると、兵役の問題では、まず弊害としては当たらないのではないか、このように思います。 それから、外交保護権をどうするかというような問題も、これは抽象的には考えられますけれども、基本的には入国した際の国籍、例えば日本とフランスの国籍を持っている人については、どこかの国に入国したとき、そのどちらかのパスポートを使って入国しているわけですので、基本的にはその関係で処理すればいいことですし、場合によっては外交上の処理で、これは十分トラブル発生することなく処理できるのではないか、このように思います。 それから、確かに、重国籍で、身分上の混乱ということで、重婚が発生するんじゃないかという指摘があります。これも、抽象的にはそれは考えられなくはないんですけれども、現実には重国籍を採用している国で重婚が頻発をして問題になったというような報告もありませんので、基本的には、抽象的には考えられるけれども、現実にはほとんど問題になっていないのではないか、このように私は考えております。もし、反論があれば、後からでも反論していただいて結構ですけれども。 旧国籍法の時代に重国籍になった場合について それで、現にこういう問題があるわけですね。今の国籍法は昭和六十年の一月一日に新しく施行されているわけですけれども、その時点でもう既に重国籍者になっていた人というのは、現在でも重国籍者として容認をされているというのが実際ではないかと思います。 割合有名な人の例を挙げて恐縮ですけれども、ペルーの元の大統領フジモリさんは重国籍者として現在でも日本におられるわけで、彼は昭和六十年の一月一日以前にもう既に重国籍者になっていたということでそのまま認められている、こういう例があるわけです。 恐らく、昭和六十年一月一日以前にもう既に重国籍者になっていて、そのまま重国籍になっているという人は案外おられるのではないかと思います。そういう人は、現実には選択をしなさいというようなことを迫っているんでしょうか。その点はどうですか。 ○房村政府参考人 御指摘のように、現在の国籍法は昭和五十九年に改正をされて六十年の一月一日から施行をされておりますが、その施行時点で既に重国籍になっていた方々につきましては、ただいま御指摘がありましたように、改正法の附則の三条で経過措置が定められております。 この方々については、現在の改正国籍法が施行される前においてはそういう国籍選択の義務が課されておりませんでしたので、そのことを考慮いたしまして、特別の扱いといたしまして、同法施行時に重国籍になったとみなされまして、一定の期限内に国籍の選択をしなかった場合には、その期限が到来したときに日本国籍の選択宣言をしたものとみなすということとなっております。 したがいまして、改正法施行時で実際に重国籍であった方々は、その期限が到来した時点で日本国籍を選択したとみなされておりますので、他の国籍を特に放棄しない限りは重国籍が継続するということになっております。 ○松野(信)委員 そうすると、そういうような方、現に重国籍、特別に外国の国籍を離脱するというふうな意思表示をしない限り重国籍が続くわけです。そういう人はどの程度あるのか、これは把握しておられますか。 ○房村政府参考人 数は把握しておりません。 国籍選択制度について ○松野(信)委員 一方では、昭和六十年の一月一日以降であれば国籍の選択を迫るということで、法律上は法務大臣の催告まで規定がしてあるわけです。それくらいある意味では厳しく、日本をとるのかそれとも外国をとるのかというふうに厳しく追及するような法律の仕組みになっているわけですが、たまたま昭和六十年の一月一日の法施行以前に重国籍者になっていた人については、余りそう厳しく言わないで事実上容認している。こういう実態にあるので、私は、こういう実態からしても、いささかちょっと不平等といいますか、重国籍を容認する方向でやはり考えていかなければならない一つのファクターではないか、このように思っております。 それで、今選択のお話をしましたけれども、これは国籍法の十五条のところで、選択を迫るという規定になっているわけで、今申し上げたように法務大臣は催告までするようになっているんですが、現実にこの規定を活用して催告をしたというような実例はあるんですか。 ○房村政府参考人 御指摘のように、国籍法十五条では法務大臣が重国籍者に国籍の選択を催告することができると定められておりますが、法務大臣がこの催告をいたしますと、期間内に具体的な選択をしないと最終的には日本国籍を失うという非常に重大な効果が生ずることとなっております。 国籍を喪失するということは、その人にとって非常に大きな意味がありますし、家族関係等にも大きな影響を及ぼすというようなことから、これは相当慎重に行うべき事柄であろうと思っておりまして、現在までこの催告を法務大臣がしたことはございません。 ○松野(信)委員 そうすると、法務大臣の催告はしないという形が現実には運用としてなされている。そうすると、実際、どういうような形で事実上選択を求めるようなことになっているかと思いますが、どのような形で重国籍の人に対して日本をとるか外国をとるかというような話をしておられるんでしょうか。 ○房村政府参考人 先ほども申し上げましたように、現在の国籍法は、できるだけ国籍は一つであることが望ましいということから、重国籍の方々につきましては、この十四条で国籍の選択という制度を設けておりまして、二十歳前に重国籍となっている方については、二十歳に達する以前であるときは二十二歳に達するまでに選択をする、その後、二十歳を過ぎてから重国籍になったときは、その重国籍になったときから二年内にいずれかの国籍を選択しなければならない、こういう国籍選択義務を定めております。 やはり、国籍というような非常にその人にとって大きな意味のあるものの選択につきましては、できる限りその方々の自発的な意思に基づいて選択をしていただくということが望ましいと考えておりますので、私どもとしては、この国籍選択の制度の意義をできるだけ知っていただく、それを踏まえて適切に選択をしていただくということが望ましいと思っておりまして、制度一般の周知に努めているというところでございます。 ○松野(信)委員 そうすると、一般的な説明をするということで、余り強制的な選択を迫るようなことはしていない、このように理解をしていいかと思います。 ここへ持ってきましたけれども、法務省が作成している「はっきりさせよう あなたの国籍」というようなチラシがありまして、「重国籍者は国籍の選択を!!」というふうに、「選択」のところがわざわざ赤く印刷されて、英語で「CHOICE」というのまで打ち出して、どうも、今局長の御説明ですと、余り強制的な形でなく一般的な説明で選択をしてもらっているというようなふうに聞こえますけれども、現実には、こういうチラシを見ますと、やはり心理的にある程度のプレッシャーをかけて、国籍選択しないとだめだということを暗にやはり強制的に運用しているんじゃないのかな、こういうふうにも思われるんですが、いかがですか。 ○房村政府参考人 先ほども申し上げましたように、私どもの考えとしては、これはできるだけ自発的に選択をしていただくということでございますが、ただ、周知をするにいたしましても、制度の趣旨がともかく選択をしていただきたいということでありますので、どうしてもそれは言葉としては選択ということを強調いたしますし、なぜ選択をしていただきたいのかということを理解していただきたくなりますので、その説明もその部分に力が置かれるということになるのではないかとは思っておりますが、なお周知の内容等については御指摘も踏まえて今後も検討していきたい、こう考えております。 ○松野(信)委員 ついでにこのチラシのことを申し上げると、「はっきりさせよう」という、この「はっきり」というところまで赤く塗って強調しておりますし、今局長の説明だと、なぜ国籍の選択をしなきゃならないかというようなことを、口頭ではおっしゃっているのかもしれませんが、このチラシを見る限り、「国籍の選択とは…」ということで、選択の方法とか選択すべき期限とか、そういうのは説明してあるんですけれども、なぜ選択をしなきゃならないのか、そこのところについては触れていない。この点は指摘をしておきたいと思います。 それで、重国籍者が具体的にどちらを選択しているのか。日本をとっているのか、それとも外国の方をとっているのか、これについては何か資料、統計というのはあるんでしょうか。つまり、国籍選択に関連する届けが、離脱とか喪失とか、そういうような届け出などから見て、どういうような選択が現実には行われているのか、統計的にはいかがでしょうか。 ○房村政府参考人 これは、国籍選択をいたしますと、国籍選択の宣言をする場合と、それから、国籍放棄の届け出をする場合とございます。そういったものの統計といたしましては、国籍選択届け出をした数、あるいは、外国国籍の喪失を届け出ていただくということもありますので、そういう数、それから国籍を喪失する国籍喪失者の数、それから国籍離脱者の数、こういったものの統計はございます。 具体的な数字も申し上げますか。(松野(信)委員「はい」と呼ぶ)例えば、平成十四年でございますと、国籍選択届け出が約二千人、それから外国国籍喪失者数が六十四名、国籍喪失者数が八百二十四名、国籍離脱者数が百六十九名、合計いたしますと約三千名ということになります。 ○松野(信)委員 私の方で事前にお聞きしていたところでは、昭和六十年一月から現在までの統計の数字で、全体として四万一千名ぐらいであるかなと聞いているんですが、その内訳をざっと御説明いただければと思います。 ○房村政府参考人 御指摘のとおり、合計いたしますと約四万一千名となります。 その内訳としては、大きく分けますと、例えば、国籍離脱が完全に重国籍者だけに限っておるわけではないものですから厳密に申し上げるのは難しいんですが、約二万人が日本国籍を取得し、約半分の二万人が外国国籍を取得しているのではないか、こう思っております。 ○松野(信)委員 それで、外国の方の国籍を選択したというのであれば、日本の国籍を離脱というような形になるかと思いますが、日本の国籍を選択するという場合には、方法としては二つあるのかなと思っております。一つは、外国の国籍を喪失したという届け、これを日本の役場あるいは大使館、領事館に出すという方法と、それから、日本の国籍を選択しますという国籍選択届をやはり同様に提出するという、二つあろうかと思うんです。 そうすると、日本の方から見れば、なるほど、日本の国籍を選択した、これがわかるわけですけれども、しかし、その人が当該外国の方の国籍を本当に外れたのかどうなのか、これは、日本政府の方としては、外国の方に問い合わせ、調査などはしているんでしょうか。 ○房村政府参考人 これは、そこまで、本国への問い合わせまでは行っておりません。 ○松野(信)委員 そうすると、現実には、これは全くの推測かと思いますが、日本に対しては日本の国籍を選びましたという国籍選択届を出しておきながら、もう一つの方の外国の方に対しては実は離脱の手続をとらなかった、あるいは、とらないままで、そのままでいたというふうになっても、日本政府の方はわからない、特別に調査しなければわからないということに現実にはなりますね。よろしいですか、それで。 ○房村政府参考人 私どもとしては、わざわざ届け出までして外国の国籍を放棄あるいは離脱したということをおっしゃっている方がそこまで虚偽の届け出をするとも思えませんので、それを信頼しているというところでございます。 今までの質疑の中間取りまとめ ○松野(信)委員 そうしますと、少しここで、中間取りまとめじゃないですけれども、まとめさせていただくと、現実には、重国籍を容認したといっても、それほど言われるような弊害というのは現に発生はしていない。諸外国でも、重国籍を容認するような諸国、これは特にG8あたりでは大変多いわけで、アメリカ、ヨーロッパあたりでは大変多いわけで、特に現実的な問題は発生していないという事実があります。 そして、先ほど指摘しましたように、現在の国籍法の施行された昭和六十年の一月一日以前に重国籍者の人は、事実上重国籍のままで、そのままになっている。また、今お話ししましたように、重国籍者が日本の国籍を選択したという選択届を出しても、外国の方については調査をしないで、それを信頼しているというふうにとどまって、もしかすると重国籍者のままになっている人もいるかもしれない、こういうような現実もある。 こういう現実を踏まえると、そういう実態を無視してまで国籍唯一の原則を維持し続けなければならない必要性というのは大変薄いのではないかな、こういうふうに私は考えているところでございます。 それで、現実にやむなく外国の国籍をとってしまった、日本人だったけれども日本人から外国人になったというような方がおられるわけで、そういう人たちを特に中心にして、重国籍を認めてほしいというような要請、陳情が最近はかなり多く出されているかと思いますが、そういうのに対してはどのように対処しておられますか。 ○房村政府参考人 先ほど来申し上げておりますように、現行の国籍法においては、考え方として、できるだけ国籍は一つにしていただきたいということが基本的な考え方でございますので、私どもとしては、現在の国籍法がそういう考え方をとっているということを御説明申し上げているというところでございます。 親の介護のために帰国する元日本人の便宜はどうなっているのか? ○松野(信)委員 私の方もいろいろ陳情、要請は受けているんですけれども、その中で、例えば、日本人であって、例えばフランスの方と結婚をされて、現在はフランスの方に住まわれていらっしゃる、そういうような人が、日本にまだお父さんやお母さんがおられて、その介護あたりで日本に帰ってくる、日本に里帰りをするというような場合、つまり、もうそのときには外国人ですので、日本人として入るわけじゃなくて、外国人として入国せざるを得ないということで、例えばお父さん、お母さんが急病だということで日本に入国する場合は、もう慌ててビザをとってやらなければいけないということで、結局観光ビザあたりで入らざるを得ないというような、そういう不便がある、こういうような指摘をされているんですが、こういう在留許可について、元日本人で、日本人の御両親あたり、親族がおられるというような場合、何らかの便宜というか何らかの便益を図るというようなことはできるんでしょうか。 ○増田政府参考人 ただいまお尋ねを受けましたようなケースの方が日本人の子供として出生した方ということでございますと、日本人の配偶者等という在留資格がございます。これに該当することになりますので、この日本人の配偶者等という在留資格で入国して在留することが可能でございます。 ○松野(信)委員 そういう話は聞くんですけれども、確かに日本人の配偶者等ということで在留許可を取りますと一年とか三年とかおれるというんですが、ただ、現実には、日本人の配偶者等というこの条件の場合には身分関係を一々証明しなきゃいけない、つまり日本から戸籍謄本などを幾つか取り寄せて、その上で申請しなきゃいけない。身分関係の証明が必要なものですから、例えばお父さん、お母さんが急病だからすぐ帰ってくれという場合には対処できないんですね。そういうようなこともありまして、なかなか不自由だというような声を現実には聞いているところなんです。 こういうような場合には、何か対処する方法というのはあるんですか。 ○増田政府参考人 至急日本に戻りたいというような場合、一番考えられるのは、やはり短期滞在査証というものをとっていただいて日本に来ていただくということが考えられます。この場合、付与する在留資格はその査証に従って付与しますので、短期滞在という在留資格を与えることになります。 ただ、短期滞在は、在留期間が十五日、三十日、九十日というふうに短い期間ではございますが、その方が日本に来てから、例えば、親の方の介護などをしている過程で、もっと日本に滞在したいという場合は、先ほど申し上げました日本人の配偶者等への在留資格の変更を申請すれば、認めることが可能でございます。 ○松野(信)委員 確かに、そういうような方法もなくはないかと思いますが、これももともと、根本的には重国籍を認めておればそう煩わしい手間暇をかけなくても対処できるのではないか、このように考えております。 それから、この重国籍については、先ほど私も申し上げたように、大体、ヨーロッパ、アメリカあたりでは、ほとんどの国が重国籍を容認する方向、あるいはもう現に容認をしているということかなと思います。近隣でいいますと、アジアの中で、中国、韓国あたりがまだ、これは日本と同じような形で重国籍を認めていない。諸外国の様子は大体そんなところかなというふうに思いますが、何かこの点について、ほかの諸外国の例でつけ加えられるところがあればと思いますが。 〔委員長退席、漆原委員長代理着席〕 ○房村政府参考人 御指摘のように、ヨーロッパあるいはアメリカにおきましては、重国籍を比較的認める方向になってきております。例えばG8の参加国では、日本とドイツを除きまして、外国への帰化により当然にはその国の国籍を喪失しないとしておりますし、欧州評議会の加盟国の間では、一九九七年のヨーロッパ国籍条約におきまして、出生や婚姻により当然に重国籍となった場合にはこれを容認しなければならない、こういう規定が設けられておりまして、この条約は既に二〇〇〇年の三月一日から発効しております。 そういう意味では、重国籍を容認する国々が相当数に上っているというのは御指摘のとおりだろうと思います。 ○松野(信)委員 今御答弁いただいたように、世界の潮流はまさに重国籍を容認していこうということではないか、政府の方もそういうふうに認識をしておられるということであります。 元日本国籍保持者の帰化について 今、帰化の話が少し出ましたけれども、やはり、もともと重国籍を持っておられて、外国の国籍を取得して日本の国籍は喪失をした、あるいは離脱をしたという方が、また日本の国籍を取得したいというふうに考えた場合、これはもう手段としては、帰化の手段しかないのかなというふうに思います。何かほかに方法があったらそれを教えていただきたいと思いますが、帰化しかないということでよろしいですよね。 そうすると、毎年、どの程度の人が現実に帰化をしておられるのか。そして、仮に、日本人で、もともと日本人であったけれども、重国籍であったために外国の国籍を選択して、その人がまた日本に帰化したいという場合、何か特別の待遇というものはあるんですか。 ○房村政府参考人 まず、帰化者数でございますが、平成十五年の帰化者数は約一万七千六百人でございます。 それから、日本国籍を失った方が再度日本に、日本人になるための帰化をする、こういう場合につきましては、国籍法の八条で、「日本の国籍を失つた者で日本に住所を有するもの」という者につきましては、住所条件、能力条件、生計条件を緩和して、容易に帰化が認められるようにという配慮をいたしております。 ○松野(信)委員 ありがとうございました。 そして、日本の場合は、国籍唯一の原則をこの帰化のところでもしっかり貫いていて、日本に帰化するのであれば、外国の国籍はもう喪失しなきゃならない、こういうふうになっているわけですね。しかし、他の諸国では必ずしもそのようには扱っていないのではないか。例えばアメリカあたりですと、アメリカに帰化するというふうになっても、従前の国の国籍が自動的になくなるわけではない、なくすという意思表示をしない限りなくならない、このように承知をしておりますが、そのほかの国、G8あたりのほかの国はどのような取り扱いをしていますか。 ○房村政府参考人 自己の志望で外国の国籍を取得したときに、その自国籍を当然に喪失するかどうかという点につきまして、アメリカは、御指摘のように自動的には喪失いたしません。そのほか、G8諸国でいきますと、イタリア、イギリス、カナダ、フランス、ロシア、これはいずれも当然には喪失いたしません。ドイツについては、喪失をする、ただし、あらかじめ国籍保有の申請をして許可証を得たときは喪失しない、そういう扱いになっております。 ○松野(信)委員 今答弁いただいたように、帰化についても、大体、世界の潮流というのは、帰化したからといって従前の国籍はなくならないという傾向にあるわけで、これまた重国籍を容認しているということであります。 それから、もう時間が余りなくなってまいりましたけれども、重国籍の問題で時々要請を受けておりますが、その要請の中に、国籍法十二条にあります国籍留保の届け出。子供さんが生まれた、例えば外国で、アメリカで日本人同士の子供さんが生まれても、日本の国籍を留保するという届けをしなきゃならない、こういう規定があって、それをしないと、日本人同士の子供であっても、例えばアメリカで生まれて、生地主義の国だとアメリカ人になって、この留保の届けをしないと日本人でなくなってしまう、こういうことになっているんです。 こういう国籍留保の届けというのは必ずしも余り周知徹底されていないし、こういうのは廃止をしたらどうかというような指摘もありますが、この点はいかがですか。 ○房村政府参考人 外国で日本人の間で子供が生まれた場合、出生届はその領事等にしていただくわけでございますが、その出生届とあわせて留保届をしていただくという形で国籍をまさに留保していただくことになっているわけでございまして、これだけ日本の方々がいろいろなところに行っておりますと、どの範囲が日本人としての国籍を持っているかということを明確にするためにはやはりこのような制度も意義があるのではないか、こう思ってはおります。 ○松野(信)委員 ただ、日本人同士が例えばアメリカで生活をして子供さんが生まれた、日本人の父、日本人の母ですよ、それで、生まれた子供は、たまたまアメリカにいて生まれると、アメリカは生地主義ですからアメリカの国籍を持つというようなことで、この留保の届けをしないと日本人でなくなってしまう。そんなばかな話があるかというのが恐らく多くの人が率直に思うところではないかなという気がしますが、その点はいかがですか。 ○房村政府参考人 御指摘のような、日本人同士の間の子供が外国で出生した場合、日本の方々はいずれも戸籍に登載されておりますので、当然、出生した子供についても、みずからの戸籍に記載をするということで出生届をしていただけるのが普通でございますので、出生届をする場合には、当然あわせて留保届ができるわけですので、もちろん周知の努力はこちらとしてもできるだけしなければならないと思っておりますが、必ずしもそれほど酷な要求をしているわけではないと思っております。 ○松野(信)委員 出生届プラス国籍留保の届けをしなきゃならないというのが今の現実なので、正直言って、これはいかがなものかという気がしております。 これまでいろいろ重国籍について議論させていただきましたけれども、いずれも、重国籍を容認してもさほど大きな弊害というのは現実にはないし、逆に重国籍者を誕生させるということで大きな便益が発生する。 私は、日本の人口というのが、これはもう御承知のように二〇〇六年をピークにどんどんと減ってしまうというようなことで、できるだけ余り日本人が減らない方がそれはいいというふうに考えておりますし、また、いわゆる重国籍者の人が日本と外国の貴重な橋渡しになる、文化とかいろいろな社会、政治の場面で大変貴重な橋渡しをして、それぞれの国に尽くしていただくという貴重な人材ではないかというふうにも思っておりまして、ぜひ重国籍を容認する方向で検討していただきたいと思いますが、最後に大臣の御所見をいただきたいと思います。 ○野沢国務大臣 国籍法につきましては、これまでも、我が国を取り巻く国際情勢や国内情勢の変化などを踏まえまして、所要の法改正を行うことも含め、適切に対応してきたところでございます。昭和二十五年、新憲法に基づく新しい現在の国籍法並びに五十九年の改正などがその主なものでございますが、今後ともに、御指摘の点を踏まえながら、国際的な動向等を注視するとともに、国民的議論を深める必要があると考えております。 委員御指摘のとおり、今後の日本人の人口動向あるいは国際交流の活発化等を考えまして、重要な課題と受けとめております。 ○松野(信)委員 もう最後ですが、この問題については参議院の法務委員会で平成十五年七月十七日にも議論がなされておりまして、民主党の千葉景子委員が質問して、最後に、国務大臣森山眞弓さん、こちらにおられますが、森山大臣も、我が国を取り巻く国際情勢とか国内情勢の変化を踏まえて適切に対処してきた、先生の御指摘は貴重な御意見で興味深く聞かせていただいた、今後とも御指摘の点を踏まえながら対処したい、こういうふうに言っておられます。 野沢大臣におかれては、それ以上の取り組み、具体的な検討をぜひ法務省内で進めていただきたい、具体的な取り組みを進めていただきたいということを申し上げて、私の質問を終わります。ありがとうございました。 〔漆原委員長代理退席、委員長着席〕
https://w.atwiki.jp/fsharpmaster/pages/35.html
スキャナが出力したPDFを、出力デバイスに合わせて変換しよう この記事はF# Advent Calender 2012の11日目(10個目)の記事です。ひとつ前の記事はyukitos22さんのTypeProvider関連の丁寧な記事で、これを書き終わったら手を動かして試してみたいところです。 さて、主催者様の「実用的な」というお題を僕はそのまま字面通りとってしまい、「仕事以外に、F#で実用的なプログラムを書いたっけ・・・」などと回想した結果ひねり出したのがこのネタです。 いささか「実用」というよりは「オレ用」という感じもしなくはないのですが・・・ 僕が富士通の名作ドキュメントスキャナS1500を購入したのは、ひとえにオライリーの「プログラミング F#」や技評の「実践F#関数型プログラミング入門」を持ち歩くのが辛かったからである、と言っていいほど僕の中でF#とS1500のつながりは実は深く、S1500でスキャンしたデータをSONY Readerで持ち歩くための変換プログラムがF#で書かれたこともまた必然と言っていいと思います。 そんなわけで、このプログラムは1年前に書いたもので、今回の記事のためにチョコチョコ直しましたが色々とアレなところがある点についてはご容赦ください。 ちなみにPDFの操作は独自実装といいたいところですが、残念ながらiTextSharpを使用しています。開発環境はVS2008です。まだVS2012買ってないんですすみません。 実行にはiTextSharpが必要なため、ここからダウンロードしてください。最新の5.3.3で動作確認しています。 機能と使い方 指定したPDFファイル(S-1500が出力したもの)から、JPEGファイルを取り出して特定のディレクトリに保存する(上のテキストボックスに元PDFのパスを入れて「PDF解体」)。出力先は「c \temp」下になります。 保存したページを画面に表示し、トリミング範囲を指定する。トリミング範囲は、左のページの左上、右下をクリックしてオレンジ色の枠を動かす。ドラッグでなく2か所クリック。右のページも同じトリミングで枠が出る。ページを送って、他のページで文字が枠からはみ出ないことを確認する。 画面サイズ(右と下のテキストボックスで指定)を指定するその際、画面いっぱいになるよう画像を縮小するか、比を変えずに天地左右に空白を入れるかも指定できる。 最後にガンマ補正のパラメータを左下のスライダーで指定し、「PDF作成」ボタンで少々待てば出力先に新しいPDFが作成される。 特筆すべき部分 全ソースがここで公開されている!(UIはC#で、コアはF#で、unsafeなところはまたC#で) だからもう自分の好きなようにいじり放題。機能追加も変更も思いのまま。ただしF#erに限る。 既存の補正ソフトがどれも「帯に短し・・・」と感じられる方は是非! ソースの見どころ? このプログラムはいろんなサンプルになっていると思います。 F#からiTextSharpを呼んでJpegを取り出す iTextSharpをF#から呼んで利用するサンプルは、今のところ日本語では見当たらないようなので、ごく部分的ではありますが紹介します。 C#からdelegateをF#側に渡し、コールバックして画面の更新を行う C#からF#の関数を呼び出すこと自体には何ら難しいことはありませんが、作業の進捗を画面に表示するため、C#からクロージャを一緒に渡してそれをF#から呼びだす方法を解説します。 この際、画面の更新はUIスレッドにしかできない、というルールを回避するための方法を例示します。 複数ページの処理をマルチコアで分散して処理 PDFファイルからイメージを取り出す処理や、複数のイメージにガンマ補正をかけたりする処理は、並行に動かしても何ら差支えがありません。こういう処理をマルチコアに分散して、全体的な処理速度を上げる方法を例示してみます。 F#からC#の関数を読んでunsafeな処理(ガンマ補正)を行う F#は僕の知る限りunsafeな処理を自分ではできません。そのため、C#で作成したライブラリに処理を託します。 F#からiTextSharpを呼んでJpegを取り出す こんな流れで進んでいきます。 ファイル名をPdfReaderに与えて、PdfReaderオブジェクトを作成 let ExtractOperation (msgcb msgCallback) (endcb endCallback) (sourcePdf string) outputPath = createDirectory outputPath let pdf = new PdfReader(sourcePdf) List.iter (OnePageFrom msgcb outputPath pdf) [1..pdf.NumberOfPages] pdfオブジェクトにページ番号を与えて、ページごとのPdfDictionaryオブジェクトを取得 let OnePageFrom (msgcb msgCallback) outputPath (pdf PdfReader) (page int) = let pg = pdf.GetPageN(page) getImages outputPath pg pdf page PdfDictionaryからリソースとxobjを取得 let getImages outputPath (dict PdfDictionary) (doc PdfReader) page = let res = PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES)) ? PdfDictionary let xobj = PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT)) ? PdfDictionary getPdfObjects xobj doc | Seq.iter (saveImage outputPath page) xobjからキーを列挙し、そのキーごとにxobjからPdfObjectを取り出し、そのサブタイプがPdfName.IMAGEであるものだけを列挙する。 let getImage (doc PdfReader) (theObj PdfObject) = let tg = PdfReader.GetPdfObject(theObj) ? PdfDictionary let subtype = PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)) ? PdfName if PdfName.IMAGE.Equals(subtype) then let xrefIdx = (theObj ? PRIndirectReference).Number let pdfObj = doc.GetPdfObject(xrefIdx) let str = pdfObj ? PdfStream let filter = tg.Get(PdfName.FILTER).ToString() match filter with | "/FlateDecode" - None | _ - Some(PdfReader.GetStreamBytesRaw(str ? PRStream)) else None let getPdfObjects (xobj PdfDictionary) (doc PdfReader) = seq { match xobj with | null - () | xobj - for key in xobj.Keys do let theObj = xobj.Get(key) if theObj.IsIndirect() then yield getImage doc theObj } 取り出すことができれば、それをbyteのストリームに見立てファイルに保存するだけです。 let parms = new System.Drawing.Imaging.EncoderParameters(1) parms.Param.[0] - new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Compression, byte 12) let saveImage outputPath pageNumber (img byte[] option) = match img with | None - () | Some image - use memStream = new System.IO.MemoryStream(image) memStream.Position - 0L use img = System.Drawing.Image.FromStream(memStream) let path = System.IO.Path.Combine(outputPath, System.String.Format(tempFileFormat, pageNumber, 1)) match jpegEncoder with | None - () | Some enc - img.Save(path, enc, parms) 逆にF#からiTextSharpを呼んでPDFを作成し、Jpegごとにページを作って貼り込む まず、最初に用紙サイズとマージンを指定してDocumentを作成し、それとファイル名を引数にPdfWriterオブジェクトを作成してそれを開きます。 let CreatePdf outputPath aspectRatio numOfPage = let margin = 0.0f let document = new Document(new iTextSharp.text.Rectangle(0.0f, 0.0f, PageSize.A4.Width, PageSize.A4.Width * aspectRatio), margin, margin, margin, margin) PdfWriter.GetInstance(document, new System.IO.FileStream(outputPath, System.IO.FileMode.Create)) | ignore document.Open () List.iter (addOnePage document aspectRatio) [1..numOfPage] document.Close(); 次に、JpegファイルごとにImageオブジェクトを作成し、位置と大きさを設定してdocumentにAddしたのち、NewPageします。これで1ページできます。これを最後のページまで繰り返すだけです。 let addOnePage (document Document) aspectRatio pageNum = let path = System.IO.Path.Combine(effectedTempPath, System.String.Format(tempFileFormat, pageNum, 1)) let jpeg = iTextSharp.text.Image.GetInstance(path) jpeg.SetAbsolutePosition(0.0f, 0.0f) jpeg.ScaleToFit(PageSize.A4.Width, PageSize.A4.Width * aspectRatio) document.Add jpeg | ignore document.NewPage() | ignore 意外に簡単ですね。 確か海外のどっかのサイトに乗っていたC#のサンプルをF#に移植しただけではなかったかと思います。 ちょっとignoreが目立つのは、僕が手を抜いていると考えてもらっていいです。あくまで「オレ用」ですんで。 C#からdelegateをF#側に渡し、コールバックして画面の更新を行う と、ここまで書いて気が付いたのですが、この件については以前にここで書いていました。 これより細かくここで書くのはちょっと無理な気がするので、こちらを参照してください。これと同じことをこのプログラムはやっています。 具体的には、進行度をメッセージするメッセージコールバックのdelegateと、終了をメッセージするdelegateをF#の関数に渡して、それをF#の中から随時Invokeしています。 C#側のコード PDFConvertLib.ExtractImagesFromPDF( delegate(string msg){ var deleg = new MessageDelegate(ExtractImageMsg); var ret = this.BeginInvoke(deleg, new object[] {msg}); }, delegate() { var deleg = new EndDelegate(ExtractImageEndOperation); var ret = this.BeginInvoke(deleg, new object[]{}); }, filePath.Text, PDFConvertLib.outputTempPath ); F#側のコード let OnePageFrom (msgcb msgCallback) outputPath (pdf PdfReader) (page int) = let pg = pdf.GetPageN(page) getImages outputPath pg pdf page sprintf "%A %d" pdf page | msgcb.Invoke // ← ココで呼びだし! let ExtractOperation (msgcb msgCallback) (endcb endCallback) (sourcePdf string) outputPath = async { createDirectory outputPath let pdf = new PdfReader(sourcePdf) [1..numberOfThreads] | List.map (ThreadRoundRobbin (OnePageFrom msgcb outputPath pdf) pdf.NumberOfPages numberOfThreads) | Async.Parallel | Async.RunSynchronously | ignore endcb.Invoke () // ← ココで呼びだし! } let ExtractImagesFromPDF (msgcb msgCallback) (endcb endCallback) (sourcePdf string) outputPath = ExtractOperation msgcb endcb sourcePdf outputPath | Async.Start | ignore 呼び出されるコードは、asyncで囲ってAsync.Startしないと別スレッドにならないため、いくら中でコールバックしても実際の画面更新はすべてすっかり終わってからになってしまいます。 複数ページの処理をマルチコアで分散して処理 C#の方も色々機能強化されて非同期処理がだいぶ得意になっていますが、それでも記述の自由さではF#に一日の長があります。 上にも書いてあるように、PDFからイメージを取り出して保存したり、取り出した画像にエフェクトをかけたりする作業はページ単位で独立しているため、並列動作が可能です。 このプログラムは当初シリアルに処理していますが、最後になってマルチコアを有効利用するように書き換えました。それが以下の部分です。 順次処理 let ExtractOperation (msgcb msgCallback) (endcb endCallback) (sourcePdf string) outputPath = async { createDirectory outputPath let pdf = new PdfReader(sourcePdf) List.iter (OnePageFrom msgcb outputPath pdf) [1..pdf.NumberOfPages] endcb.Invoke () } 並列化 let ThreadRoundRobbin theMethod max cntThread n = async { List.iter theMethod [n..cntThread..max] } let ExtractOperation (msgcb msgCallback) (endcb endCallback) (sourcePdf string) outputPath = async { createDirectory outputPath let pdf = new PdfReader(sourcePdf) [1..numberOfThreads] | List.map (ThreadRoundRobbin (OnePageFrom msgcb outputPath pdf) pdf.NumberOfPages numberOfThreads) | Async.Parallel | Async.RunSynchronously | ignore endcb.Invoke () } ThreadRoundRobbinは、ページごとに処理を指定数のスレッドに振り分ける関数です。スレッド数が4なら、最初にスレッドにはページ1,5,9,13...が、二つ目には2,6,10.14...が、三つめには3,7,11,15...が、四つ目には4,8,12,16...が割り振られ、それがAsync.Parallelで並列に動作し、Async.RunSynchronouslyですべての処理の終了を待ってendcb.Invoke(終了通知処理)を呼び出すようになっています。 今回はこんな方法をとったのですが、何も考えずに全ページをasyncしてもページ数が少なければそれなりに動きます。ただ、あまりページが多いとエラーになるようです。 F#からC#の関数を読んでunsafeな処理(ガンマ補正)を行う C#でFastBitmapなるクラスを作り、最初にガンマ値を与えて補正テーブルを作成してから、ビットマップごとにピクセル単位でをかけています。去年どこかで見たソースそのままだったような・・・ そんなわけなのでここでは掲載しませんが、興味がある方はソースを覗いてみてください。 と思ったら、.Netの機能でガンマ補正ってかけられるんですね・・・トホホ。しかも1.1からあるみたいだし。去年何を調べたんだ。 ImageAttributes.SetGamma 終わりに という具合でざっくり説明してきましたが「全部C#でかける」とか言わないでこのF#の濃密なソースを楽しんでもらえれば幸いです。 ソースはとバイナリはこのページ最下部の添付ファイルからダウンロード(S1500PDfConverter.zip)できますが、後日Githubにもあげようと思っています。そしたらみなさんで好きなように機能拡張してください。僕も使いますので。 サポート すみません。2013年2月24日以前のソースでは「C \temp\pdfeffected」ディレクトリをプログラム内部で作っていなかったため、このディレクトリがないとPDF作成時に落ちてしまいます。最新版をダウンロードしなおすか、このディレクトリをあらかじめ作成しておいてください。m(_ _)m (文責:片山 功士 2012/12/11) 今日: - 人 昨日: - 人 トータル: - 人